package services

import (
	"encoding/json"
	"errors"

	"io/ioutil"
	"os"

	"github.com/deploy-services/v2/log"

	"github.com/deploy-services/v2/filesystem"
	"github.com/deploy-services/v2/kcfg"
)

type packaged struct {
	source        []string
	s_info        map[string]source_info
	s_info_update bool
}

func (s *packaged) uncompress_source(sc string) error {
	sc_path := filesystem.GetLocalPackageFilePath(sc)
	stat, err := os.Stat(sc_path)
	if os.IsNotExist(err) {
		log.Println("packaged", "Uncompress ", sc_path, "Not Found")
		return NotFound
	}

	new_info := source_info{
		File: sc_path,
		Size: stat.Size(),
		Time: stat.ModTime().Format("2006-01-02 15:04:05"),
	}
	if info, ok := s.s_info[sc]; ok {
		if new_info.Size == info.Size && new_info.Time == info.Time {
			log.Println("packaged", "Uncompress ", sc_path, "No Need Update")
			return NoNeedUpdate
		}
	}

	err = filesystem.UnpackTarGz(sc_path, filesystem.GetLocalDataFilePath())
	if err != nil {
		log.Println("packaged", "Uncompress ", sc_path, "Failed", err)
		return err
	}

	// 然后保存 source 文件信息
	// 所有服务都更新完成时，将 info 文件更新到磁盘
	s.s_info[sc] = new_info
	s.s_info_update = true
	log.Println("packaged", "Commit", sc_path, "Completed")
	return nil
}

func (s *packaged) commit() ([]string, []error) {
	s.s_info_update = false
	files := []string{}
	errs := []error{}
	for _, sc := range s.source {
		files = append(files, sc)
		if err := s.uncompress_source(sc); err != nil {
			log.Println("packaged", "Uncompress", sc, err)
			errs = append(errs, err)
			continue
		}
		errs = append(errs, nil)
	}

	if s.s_info_update {
		source_path := filesystem.GetLocalPackagedSourcePath()
		buff, _ := json.MarshalIndent(s.s_info, "", "\t")
		ioutil.WriteFile(source_path, buff, 0755)
	}
	return files, errs
}

func push(file string, content []byte) error {
	path := filesystem.GetLocalPackageFilePath(file)
	err := ioutil.WriteFile(path, content, 0666)
	if err != nil {
		return errors.New(path + " " + err.Error())
	}
	return nil
}

func parsePackaged(n *kcfg.Node) packaged {
	s := packaged{
		source: []string{},
		s_info: make(map[string]source_info),
	}
	sources, _ := n.ChildsAllWithoutNote()
	if len(sources) == 0 {
		log.Println("No Any Package")
	}
	for _, v := range sources {
		if allow_source_type(v) {
			s.source = append(s.source, v)
		} else {
			log.Println("Not Support", v)
		}
	}

	source_path := filesystem.GetLocalPackagedSourcePath()
	buff, err := ioutil.ReadFile(source_path)
	if err == nil {
		json.Unmarshal(buff, &s.s_info)
	}

	return s
}
